#include "memdb/impl/simple/SimpleDB.h"

#include "memdb/impl/simple/SimpleTables.h"
#include "memdb/impl/simple/Factory.h"
#include "memdb/error/MemdbError.h"
//TODO:  Factory & _factory = FactoryCreator::instance().create(DBFactory::Simple);

namespace memdb {
namespace impl {
namespace simple {

SimpleDB::SimpleDB(const std::string & name, const std::string & dir)
: _name(name)
, _dir(dir)
, _factory(new Factory(_dir/_name))
{
  open();
}

SimpleDB::~SimpleDB(){
  close();
}

const std::filesystem::path & SimpleDB::dbPath() const {
	return _factory->dbPath();
}

bool SimpleDB::exists() const {
  return std::filesystem::exists(dbPath());
}

std::error_code SimpleDB::destroy() {
  if(exists()){
		std::error_code ec;
    std::filesystem::remove_all(dbPath(), ec);
		return ec;
  }
  return memdb::error::db_not_exists;
}



std::error_code SimpleDB::_create() {
  if(std::filesystem::create_directories(dbPath())){
    _meta = std::move(_factory->createMeta());

    if(auto && ec = _meta->open(); ec){
      return ec;
    }

		_tables = std::move( std::unique_ptr<ITables>(new SimpleTables(*_meta, *_factory)));
    return memdb::error::ok;
  }
  return memdb::error::fs_create_directory_error;
}
std::error_code SimpleDB::_open() {
  _meta = std::move(_factory->createMeta());

  if(auto && ec = _meta->open(); ec){
    return ec;
  }

	_tables = std::move( std::unique_ptr<ITables>(new SimpleTables(*_meta, *_factory)));
  return memdb::error::ok;
}



std::error_code SimpleDB::open() {
	if(isOpened() == false){
		auto && ec = !exists() ? _create() : _open();
		if(ec){
			return ec;
		}
		_opened = true;
		return ec;
	}
	return memdb::error::ok;
}
std::error_code SimpleDB::close() {
	if(isOpened()){
		_tables.reset();

		if(auto && ec = _meta->close(); ec){
			return ec;
		}

		_meta.reset();

		_opened = false;
		return memdb::error::ok;
	}
	return memdb::error::ok;
}

ITables & SimpleDB::tables() const {
  return *_tables;
}


}//namespace simple
}//namespace impl
}//namespace memdb
